package com.colin.library.base;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import com.colin.library.help.StringHelp;
import com.colin.library.help.ToastHelp;
import com.colin.library.listener.IAlertCallBack;
import com.colin.library.listener.IAlertListCallBack;
import com.colin.library.listener.IAlertMultipleListCallBack;
import com.colin.library.manager.AppActivityManager;
import com.colin.library.other.AppException;
import com.colin.library.view.progress.MyProgressBar;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import static android.R.attr.inputType;
import static android.content.Context.INPUT_METHOD_SERVICE;

/**
 * Created by Colin on 2016/12/30.
 */

public abstract class BaseFragment extends Fragment implements BaseView {
    public interface OnFragmentListener {
        //fragment编号；item位置，判断,回调数据
        void onFragmentClick(int fragment_id, boolean isOK, int position, Object object);
    }

    protected OnFragmentListener mListener = null;
    /**
     * context
     */
    protected static Activity activity = null;
    protected View fragment_view = null;
    private boolean isLoading = false;
    protected Dialog dialog = null;
    /**
     * Screen information
     */
    protected int mScreenWidth = 0;
    protected int mScreenHeight = 0;
    protected float mScreenDensity = 0.0f;
    protected int alert_what = -1;
    @NonNull
    protected Map<Integer, Dialog> dialogMap = new HashMap<>();
    /**
     * Log tag
     */
    protected String TAG = null;

    private boolean isFirstResume = true;
    private boolean isFirstVisible = true;
    private boolean isFirstInvisible = true;
    private boolean isPrepared;

    @Override
    public boolean isLoading() {
        return isLoading;
    }

    public void setLoading(boolean loading) {
        isLoading = loading;
    }

    /**
     * @param context
     */
    @Override
    public void onAttach(Context context) {
        TAG = this.getClass().getSimpleName();
        this.activity = (Activity) context;
        super.onAttach(context);
        if (context instanceof OnFragmentListener) {
            mListener = (OnFragmentListener) context;
        } else {
            throw new AppException(context.toString() + "界面必须实现OnFragmentListener接口");
        }
    }

    @Override
    public void onAttach(Activity activity) {
        this.activity = activity;
        super.onAttach(activity);
    }

    /**
     * 感谢stack overflow上的Marcus Forsell Stahre提供的高级解决方案<br/>
     * 此问题是android系统bug，详细情况如下：<br/>
     * This seems to be a bug in the newly added support for nested fragments.
     * Basically, the child FragmentManager ends up with a broken internal state
     * when it is detached from the activity. A short-term workaround that fixed
     * it for me is to add the following to onDetach() of every Fragment which
     * you call getChildFragmentManager() on.<br/>
     * If you look at the implementation of Fragment, you'll see that when
     * moving to the detached state, it'll reset its internal state. However, it
     * doesn't reset mChildFragmentManager (this is a bug in the current version
     * of the support library). This causes it to not reattach the child
     * fragment manager when the Fragment is reattached, causing the exception
     * you saw. <br/>
     * Marcus Forsell Stahre Apr 3 '13 at 10:32
     */
    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (initViewLayoutID() != 0) {
            return fragment_view = inflater.inflate(initViewLayoutID(), container, false);
        } else {
            return fragment_view = super.onCreateView(inflater, container, savedInstanceState);
        }
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mScreenDensity = displayMetrics.density;
        mScreenHeight = displayMetrics.heightPixels;
        mScreenWidth = displayMetrics.widthPixels;

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initPrepare();
    }


    /**
     * 隐藏键盘
     */
    @Override
    public void hideKeyword() {
        InputMethodManager imm = ((InputMethodManager) activity.getSystemService(INPUT_METHOD_SERVICE));
        if (imm != null && activity.getCurrentFocus() != null) {
            imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }


    @Override
    public void setTitle(String title) {

    }

    /**
     * 网络请求开始 开启网络请求的弹出框
     *
     * @param is_show_loading
     */
    @Override
    public void httpStart(boolean is_show_loading) {
        setLoading(true);
        if (is_show_loading && !isAlertShowing(ALERT_LOADING)) {
            this.alert_what = ALERT_LOADING;
            dialog = new MyProgressBar(activity, getString(R.string.dialog_loading));
            dialog.setCancelable(false);
            dialogMap.put(this.alert_what, dialog);
            dialog.show();
        }
    }

    /**
     * 网络请求结束
     *
     * @param is_show_loading
     */
    @Override
    public void httpEnd(boolean is_show_loading) {
        setLoading(false);
        if (is_show_loading) {
            closeAlert(ALERT_LOADING);
        }
    }


    /**
     * 普通提示
     *
     * @param string_id
     */
    @Override
    public void toastShow(@StringRes int string_id) {
        toastShow(getString(string_id));
    }

    /**
     * 普通提示
     *
     * @param msg
     */
    @Override
    public void toastShow(@NonNull String msg) {
        //        防止遮盖虚拟按键
        if (!StringHelp.isEmpty(msg) && fragment_view != null) {
            Snackbar.make(fragment_view, msg, Snackbar.LENGTH_SHORT).show();
        } else if (fragment_view == null && !StringHelp.isEmpty(msg)) {
            ToastHelp.showShort(msg);
        }
    }

    /**
     * 是否有弹出框显示
     *
     * @return
     */
    @Override
    public boolean isAlertShowing() {
        boolean isShowing = false;
        for (Map.Entry<Integer, Dialog> dialogEntry : dialogMap.entrySet()) {
            if (dialogEntry.getValue().isShowing()) {
                isShowing = true;
            }
        }
        return isShowing;
    }

    /**
     * 某个弹出框是否显示中
     *
     * @param alert_what
     * @return
     */
    @Override
    public boolean isAlertShowing(@IntRange int alert_what) {
        return dialogMap.get(alert_what) != null && dialogMap.get(alert_what).isShowing();
    }

    @Override
    public void alertShow(String message) {
        this.alertShow(getString(R.string.notice), message);
    }

    @Override
    public void alertShow(String title, String message) {
        this.alertShow(ALERT_PROMPT, title, message, null);
    }

    @Override
    public void alertShow(int alert_what, String message) {
        this.alertShow(alert_what, getString(R.string.notice), message, null);
    }

    @Override
    public void alertShow(int alert_what, String title, String message, final IAlertCallBack iAlertCallBack) {
        if (isAlertShowing(alert_what)) {
            return;
        }

        this.alert_what = alert_what;

        title = StringHelp.isEmpty(title) ? getString(R.string.notice) : title;
        message = StringHelp.isEmpty(message) ? getString(R.string.notice) : message;
        if (null == iAlertCallBack) {
            dialog = new android.support.v7.app.AlertDialog.Builder(activity)
                    .setCancelable(false)
                    .setTitle(title)
                    .setMessage(message)
                    .setNeutralButton(R.string.iknow, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).create();
        } else {
            dialog = new android.support.v7.app.AlertDialog.Builder(activity)
                    .setCancelable(false)
                    .setTitle(title)
                    .setMessage(message)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (iAlertCallBack != null) {
                                iAlertCallBack.alertCallBack(true, null);
                            }
                        }
                    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (iAlertCallBack != null) {
                                iAlertCallBack.alertCallBack(false, null);
                            }
                        }
                    }).create();
        }
        dialogMap.put(this.alert_what, dialog);

        dialog.show();

    }

    @Override
    public void alertEdit(String title, String message, IAlertCallBack iAlertCallBack) {
        this.alertEdit(title, message, InputType.TYPE_CLASS_TEXT, iAlertCallBack);
    }

    @Override
    public void alertEdit(String title, String message, int inPutType, final IAlertCallBack iAlertCallBack) {
        if (isAlertShowing(ALERT_EDIT)) {
            return;
        }
        this.alert_what = ALERT_EDIT;

        View dialogView = LayoutInflater.from(activity).inflate(R.layout.layout_dialog_edittext, null);
        final EditText edit_alert_show = (EditText) dialogView.findViewById(R.id.edit_alert_show);
        edit_alert_show.setInputType(inputType);
        edit_alert_show.setHint(message);
        dialog = new AlertDialog.Builder(activity)
                .setView(dialogView)
                .setTitle(title)
                .setCancelable(false)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        iAlertCallBack.alertCallBack(true, StringHelp.getText(edit_alert_show));
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        iAlertCallBack.alertCallBack(false, StringHelp.getText(edit_alert_show));
                        dialog.dismiss();
                    }
                })
                .create();

        dialogMap.put(this.alert_what, dialog);

        dialog.show();

    }

    @Override
    public void alertList(String[] array, IAlertListCallBack iAlertListCallBack) {
        this.alertList(getString(R.string.choose), -1, array, iAlertListCallBack);
    }

    @Override
    public void alertList(String title, int position, final String[] array, final IAlertListCallBack callBack) {
        if (isAlertShowing(ALERT_LIST)) {
            return;
        }
        this.alert_what = ALERT_LIST;
        final int[] dialog_choose_position = new int[1];
        final String[] dialog_choose_object = new String[1];

        dialog = new AlertDialog.Builder(activity)
                .setCancelable(false)
                .setTitle(title)
                .setSingleChoiceItems(array, position, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog_choose_position[0] = which;
                        dialog_choose_object[0] = array[which];
                    }
                })
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                        if (callBack != null) {
                            callBack.alertCallBack(true, dialog_choose_position[0], dialog_choose_object[0]);
                        }
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                    }
                }).create();
        android.view.WindowManager.LayoutParams p = dialog.getWindow().getAttributes();  //获取对话框当前的参数值
        p.height = (int) (mScreenHeight * 0.6);   //高度设置为屏幕的0.5
        dialog.getWindow().setAttributes(p);     //设置生效


        dialogMap.put(this.alert_what, dialog);

        dialog.show();


    }

    @Override
    public void alertMultiList(String[] array, IAlertMultipleListCallBack callBack) {
        this.alertMultipleList(getString(R.string.choose), null, array, callBack);
    }

    @Override
    public void alertMultipleList(String title, boolean[] positionArray, String[] array, final IAlertMultipleListCallBack callBack) {
        if (isAlertShowing(ALERT_LIST)) {
            return;
        }
        this.alert_what = ALERT_LIST;
        //初始化选中的值
        final boolean[] dialog_choose_position = new boolean[array.length];
        final String[] dialog_choose_object = new String[array.length];

        if (null == positionArray || positionArray.length != array.length) {
            positionArray = new boolean[array.length];
            for (int i = 0; i < array.length; i++) {
                positionArray[i] = false;
            }
        }

        for (int i = 0; i < positionArray.length; i++) {
            dialog_choose_position[i] = positionArray[i];
        }


        dialog = new AlertDialog.Builder(activity)
                .setCancelable(false)
                .setTitle(title)
                .setMultiChoiceItems(array, positionArray, new DialogInterface.OnMultiChoiceClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                        dialog_choose_position[which] = isChecked;
                    }
                })
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                        if (callBack != null) {
                            callBack.alertCallBack(true, dialog_choose_position, dialog_choose_object);
                        }
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                    }
                }).create();
        android.view.WindowManager.LayoutParams p = dialog.getWindow().getAttributes();  //获取对话框当前的参数值
        p.height = (int) (mScreenHeight * 0.6);   //高度设置为屏幕的0.5
        dialog.getWindow().setAttributes(p);     //设置生效

        dialogMap.put(this.alert_what, dialog);

        dialog.show();
    }


    /**
     * 关闭所有弹出框
     */
    @Override
    public void closeAlert() {
        for (Map.Entry<Integer, Dialog> dialogEntry : dialogMap.entrySet()) {
            dialogEntry.getValue().dismiss();
            dialogMap.remove(dialogEntry.getKey());
        }
        dialogMap.clear();
    }

    /**
     * 关闭指定弹出框
     */
    @Override
    public void closeAlert(@IntRange int alert_what) {
        if (isAlertShowing(alert_what) || null != dialogMap.get(alert_what)) {
            dialogMap.get(alert_what).dismiss();
            dialogMap.remove(alert_what);
        }
    }

    /**
     * 界面跳转
     *
     * @param target
     * @param bundle
     * @param closeSelf
     */
    @Override
    public void startActivity(@NonNull String target, @Nullable Bundle bundle, @NonNull boolean closeSelf) {
        Class clazz = null;
        try {
            clazz = Class.forName(target);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (clazz != null) {
            hideKeyword();
            if (closeSelf) {
                this.closeActivity();
            }
            Intent intent = new Intent(activity, clazz);
            //android5.0之后隐式启动是禁止的；你需要加上这句代码
            intent.setPackage(activity.getPackageName());
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
            showOpenAnim();
        }
    }

    @Override
    public void startActivity(@NonNull Class<? extends Activity> target, @Nullable Bundle bundle, @NonNull boolean closeSelf) {
        if (closeSelf) {
            this.closeActivity();
        }
        Intent intent = new Intent(activity, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        this.startActivity(intent);
        showOpenAnim();
    }

    @Override
    public void startActivityForResult(@NonNull Class<? extends Activity> target, int requestCode, @NonNull Bundle bundle) {
        Intent intent = new Intent(activity, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        this.startActivityForResult(intent, requestCode);
        showOpenAnim();
    }

    @Override
    public void closeActivity() {
        hideKeyword();
        AppActivityManager.getInstance().removeActivity(activity);
        showCloseAnim();
    }


    /**
     * 启动界面：显示动画
     */
    protected void showOpenAnim() {
        activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
    }

    /**
     * 关闭界面：显示动画
     */
    protected void showCloseAnim() {
        activity.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
    }


    //Fragment专有
    private synchronized void initPrepare() {
        if (isPrepared) {
            onFirstUserVisible();
            initPresenter();
            initView();
            initData();
            initListener();
            initAsync();
        } else {
            isPrepared = true;
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            if (isFirstVisible) {
                isFirstVisible = false;
                initPrepare();
            } else {
                onUserVisible();
            }
        } else {
            if (isFirstInvisible) {
                isFirstInvisible = false;
                onFirstUserInvisible();
            } else {
                onUserInvisible();
            }
        }
    }

    /**
     * 当碎片是可见的第一次，在这里我们可以做一些初始化的工作或刷新数据只有一次
     */
    protected abstract void onFirstUserVisible();

    /**
     * 类似碎片的onResume()的生命周期方法
     */
    protected abstract void onUserVisible();

    /**
     * 当碎片第一次不可见的时候
     */
    private void onFirstUserInvisible() {
        // here we do not recommend do something
    }

    /**
     * 类似碎片的onPause()的生命周期方法
     */
    protected abstract void onUserInvisible();
}
